//建造者模式
//主要用来完成复杂对象的构建过程
// 使⽤多个简单的对象⼀步⼀步构建成⼀个复杂的对象，能够将⼀个复杂的对象的构建与它的表⽰分离，提供⼀种创建对象的最佳⽅式。
// 主要⽤于解决对象的构建过于复杂的问题。
#include <iostream>
#include <string>
#include <memory>

//笔记本电脑基类
class Computer
{
public:
    Computer() {}
    void setBoard(const std::string &board)
    {
        _board = board;
    }
    void setDisplay(const std::string &display)
    {
        _display = display;
    }
    virtual void setOs() = 0;
    std::string toString()
    {
        std::string computer = "Computer:{\n";
        computer += "\tboard=" + _board + ",\n";
        computer += "\tdisplay=" + _display + ",\n";
        computer += "\tOs=" + _os + ",\n";
        computer += "}\n";
        return computer;
    }

protected:
    std::string _board;
    std::string _display;
    std::string _os;
};


//实现一个Mac笔记本电脑类
//配置OS
class MacBook : public Computer
{
public:
    MacBook() {}
    void setOs()
    {
        _os = "Mac Os X12";
    }
};


//实现一个建造者基类，包含产品对象的各个接口
class Builder
{
public:
    virtual void buildBoard(const std::string &board) = 0;
    virtual void buildDisplay(const std::string &diaplay) = 0;
    virtual void buildOs() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};


//实现一个建造者子类：笔记本电脑的建造者类
class MacBookBulider : public Builder
{
public:
    MacBookBulider() : _computer(new MacBook()) {}
    void buildBoard(const std::string &board)
    {
        _computer->setBoard(board);
    }
    void buildDisplay(const std::string &display)
    {
        _computer->setDisplay(display);
    }
    void buildOs()
    {
        _computer->setOs();
    }
    std::shared_ptr<Computer> build()
    {
        return _computer;
    }
private:
    std::shared_ptr<Computer> _computer;
};


//指挥者类：通过指挥者来构造产品
class Director
{
public:
    Director(Builder *builder) : _builder(builder)
    {
    }
    void construct(const std::string &board, const std::string &diaplay)
    {
        _builder->buildBoard(board);
        _builder->buildDisplay(diaplay);
        _builder->buildOs();
    }

private:
    Builder *_builder;
};


int main()
{
    Builder *builder = new MacBookBulider();
    std::unique_ptr<Director> pd(new Director(builder));

    pd->construct("英特尔主板", "VOC显示器");
    std::shared_ptr<Computer> computer = builder->build();
    std::cout << computer->toString() << std::endl;
    return 0;
}